import random
from datetime import datetime

class GomokuAI:
    def __init__(self, board_size=15, difficulty=1):
        self.board_size = board_size
        self.board = [[0 for _ in range(board_size)] for _ in range(board_size)]
        self.current_player = 1  # 1表示黑棋，2表示白棋
        self.game_over = False
        self.winner = 0
        self.difficulty = difficulty  # 1=初级, 2=中级, 3=高级
        self.move_history = []  # 记录每一步的历史

    def reset_game(self):
        """重置游戏状态"""
        self.board = [[0 for _ in range(self.board_size)] for _ in range(self.board_size)]
        self.current_player = 1
        self.game_over = False
        self.winner = 0
        self.move_history = []

    def is_valid_move(self, x, y):
        """检查落子位置是否有效"""
        return 0 <= x < self.board_size and 0 <= y < self.board_size and self.board[x][y] == 0

    def make_move(self, x, y, player):
        """在指定位置落子"""
        if self.is_valid_move(x, y):
            self.board[x][y] = player

            # 记录这一步
            move_time = datetime.now().strftime("%H:%M:%S")
            move_position = f"{chr(ord('A') + y)}{x + 1}"
            move_player = "黑棋" if player == 1 else "白棋"
            self.move_history.append(f"{len(self.move_history) + 1}. {move_player} {move_position} ({move_time})")

            # 检查是否获胜
            self.check_winner(x, y, player)
            return True
        return False

    def check_winner(self, x, y, player):
        """检查是否有玩家获胜"""
        directions = [(0, 1), (1, 0), (1, 1), (1, -1)]  # 水平、垂直、对角线、反对角线

        for dx, dy in directions:
            count = 1  # 当前位置已经有一个棋子

            # 检查正方向
            i, j = x + dx, y + dy
            while 0 <= i < self.board_size and 0 <= j < self.board_size and self.board[i][j] == player:
                count += 1
                i += dx
                j += dy

            # 检查反方向
            i, j = x - dx, y - dy
            while 0 <= i < self.board_size and 0 <= j < self.board_size and self.board[i][j] == player:
                count += 1
                i -= dx
                j -= dy

            if count >= 5:
                self.game_over = True
                self.winner = player
                return True

        return False

    def ai_move_easy(self):
        """简单难度AI落子（随机选择有效位置）"""
        valid_moves = []
        for i in range(self.board_size):
            for j in range(self.board_size):
                if self.is_valid_move(i, j):
                    valid_moves.append((i, j))

        if valid_moves:
            return random.choice(valid_moves)
        return None, None

    def ai_move_medium(self):
        """中等难度AI落子（会尝试连成线和阻止玩家连成线）"""
        # 检查自己是否有机会连成4子
        for i in range(self.board_size):
            for j in range(self.board_size):
                if self.is_valid_move(i, j):
                    self.board[i][j] = 2  # 假设AI在这里落子
                    if self.check_winner(i, j, 2):
                        self.board[i][j] = 0  # 撤销假设
                        return i, j
                    self.board[i][j] = 0  # 撤销假设

        # 检查玩家是否有机会连成4子，进行阻挡
        for i in range(self.board_size):
            for j in range(self.board_size):
                if self.is_valid_move(i, j):
                    self.board[i][j] = 1  # 假设玩家在这里落子
                    if self.check_winner(i, j, 1):
                        self.board[i][j] = 0  # 撤销假设
                        return i, j
                    self.board[i][j] = 0  # 撤销假设

        # 如果没有明显的威胁或机会，选择靠近中心或已有棋子的位置
        valid_moves = []
        center_x, center_y = self.board_size // 2, self.board_size // 2

        for i in range(self.board_size):
            for j in range(self.board_size):
                if self.is_valid_move(i, j):
                    # 计算到中心的距离和到最近棋子的距离
                    dist_to_center = abs(i - center_x) + abs(j - center_y)

                    # 计算到最近棋子的距离
                    min_dist_to_piece = float('inf')
                    for x in range(self.board_size):
                        for y in range(self.board_size):
                            if self.board[x][y] != 0:
                                dist = abs(i - x) + abs(j - y)
                                if dist < min_dist_to_piece:
                                    min_dist_to_piece = dist

                    # 综合评分：距离中心越近、距离已有棋子越近分数越高
                    score = 10 - dist_to_center + (5 if min_dist_to_piece <= 2 else 0)
                    valid_moves.append((i, j, score))

        if valid_moves:
            # 按分数排序，选择分数最高的位置
            valid_moves.sort(key=lambda x: x[2], reverse=True)
            return valid_moves[0][0], valid_moves[0][1]

        # 如果没有找到合适的位置，随机选择
        return self.ai_move_easy()

    def ai_move_hard(self):
        """困难难度AI落子（使用简单的极小极大算法）"""
        # 检查自己是否有机会连成4子
        for i in range(self.board_size):
            for j in range(self.board_size):
                if self.is_valid_move(i, j):
                    self.board[i][j] = 2  # 假设AI在这里落子
                    if self.check_winner(i, j, 2):
                        self.board[i][j] = 0  # 撤销假设
                        return i, j
                    self.board[i][j] = 0  # 撤销假设

        # 检查玩家是否有机会连成4子，进行阻挡
        for i in range(self.board_size):
            for j in range(self.board_size):
                if self.is_valid_move(i, j):
                    self.board[i][j] = 1  # 假设玩家在这里落子
                    if self.check_winner(i, j, 1):
                        self.board[i][j] = 0  # 撤销假设
                        return i, j
                    self.board[i][j] = 0  # 撤销假设

        # 检查自己是否有机会连成3子
        for i in range(self.board_size):
            for j in range(self.board_size):
                if self.is_valid_move(i, j):
                    self.board[i][j] = 2  # 假设AI在这里落子
                    # 简化的3子检查
                    has_three = self.check_three_in_a_row(i, j, 2)
                    self.board[i][j] = 0  # 撤销假设
                    if has_three:
                        return i, j

        # 检查玩家是否有机会连成3子，进行阻挡
        for i in range(self.board_size):
            for j in range(self.board_size):
                if self.is_valid_move(i, j):
                    self.board[i][j] = 1  # 假设玩家在这里落子
                    # 简化的3子检查
                    has_three = self.check_three_in_a_row(i, j, 1)
                    self.board[i][j] = 0  # 撤销假设
                    if has_three:
                        return i, j

        # 没有明显威胁或机会，选择靠近中心或已有棋子的位置
        return self.ai_move_medium()

    def check_three_in_a_row(self, x, y, player):
        """检查是否能形成3子连线（简化版）"""
        directions = [(0, 1), (1, 0), (1, 1), (1, -1)]

        for dx, dy in directions:
            count = 1

            # 正方向
            i, j = x + dx, y + dy
            while 0 <= i < self.board_size and 0 <= j < self.board_size and self.board[i][j] == player:
                count += 1
                i += dx
                j += dy

            # 反方向
            i, j = x - dx, y - dy
            while 0 <= i < self.board_size and 0 <= j < self.board_size and self.board[i][j] == player:
                count += 1
                i -= dx
                j -= dy

            if count >= 3:
                return True

        return False

    def get_ai_move(self):
        """根据难度等级获取AI落子位置"""
        if self.difficulty == 1:
            return self.ai_move_easy()
        elif self.difficulty == 2:
            return self.ai_move_medium()
        else:
            return self.ai_move_hard()

    def convert_to_robot_command(self, x, y, player):
        """将棋盘坐标转换为机器人控制命令"""
        col_char = chr(ord('A') + y)
        row_num = x + 1
        color = 'W' if player == 2 else 'B'
        return f"{color} {col_char}{row_num}"

    def print_game_history(self):
        """打印完整的棋局历史"""
        print("\n===== 完整棋局记录 =====")
        print(f"难度: {'初级' if self.difficulty == 1 else '中级' if self.difficulty == 2 else '高级'}")
        print(f"胜利者: {'黑棋' if self.winner == 1 else '白棋' if self.winner == 2 else '平局'}")
        print("步数记录:")

        for move in self.move_history:
            print(move)